package com.tjresearch.redisdbtasktracker.runner;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.ltsopensource.core.domain.Action;
import com.github.ltsopensource.core.logger.Logger;
import com.github.ltsopensource.core.logger.LoggerFactory;
import com.github.ltsopensource.spring.boot.annotation.JobRunner4TaskTracker;
import com.github.ltsopensource.tasktracker.Result;
import com.github.ltsopensource.tasktracker.logger.BizLogger;
import com.github.ltsopensource.tasktracker.runner.JobContext;
import com.github.ltsopensource.tasktracker.runner.JobRunner;
import com.tjresearch.redisdbtasktracker.pojo.BuildMain;
import com.tjresearch.redisdbtasktracker.pojo.HfData;
import com.tjresearch.redisdbtasktracker.service.JobService;

@JobRunner4TaskTracker
public class JobRunnerImpl implements JobRunner {
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	private static final Logger LOGGER = LoggerFactory.getLogger(JobRunnerImpl.class);
	@Autowired
	private RateCal rateCal;
	@Autowired
	private JobService jobService;

	@Autowired
	private TimeChartsController timeChartsController;
	/*
	 * 都是全量数据
	 * 
	 * 
	 */
	@Override
	public Result run(JobContext jobContext) throws Throwable {
		
		try {
			BizLogger bizLogger = jobContext.getBizLogger();
			LOGGER.info("即将执行：" + jobContext);
			Map<String, String> jobExtParams = jobContext.getJob().getExtParams();
			if (jobExtParams != null) {
				String init = jobExtParams.get("init");
				if (init != null && init.equalsIgnoreCase("true")) {
					jobService.truncateSourceData();//导入全量的时候需要将source表进行删除
					jobService.truncateDailyData();//全量将daily表删除
					LOGGER.info("执行全量数据导入");

				} else {
					LOGGER.info("执行增量数据导入");
				}
			}
			//从redis获取三一的填充数据
			List<BuildMain> mainFillDataList = findSanyiMainFillData();
			if(mainFillDataList!=null && mainFillDataList.size()>0){
				System.out.println("导入三一重工的数据");
				jobService.truncateMainFill();
				//将数据导入到build_main_indexfill中
				jobService.batchInsertBuildFill(mainFillDataList);
			}
			redisToDB();
			
			jobService.truncateHighfreqData();
			System.out.print("truncate highfreq data done!");
			rateCal.fetchBuildMainIndexToDailyData();
			System.out.println("insert table highdailydata");
			rateCal.v7Function1InitDailyData();
			rateCal.v7Function2InitDailyData();
			System.out.println("start calculate mom");
			rateCal.momAll();
			System.out.println("calculate mom done");
			rateCal.yoyAll();
			System.out.println("calculate yoy done");
			rateCal.pobAll();
			System.out.println("calculate pob done");
			LOGGER.info("执行图片生成");
			timeChartsController.getHighfreqData();

			LOGGER.info("执行结束");
			jobContext.getJob().getExtParams();
			// 会发送到 LTS (JobTracker上)
			bizLogger.info("将数据导入到mysql中");

		} catch (Exception e) {
			LOGGER.info("Run job failed!", e);
			return new Result(Action.EXECUTE_FAILED, e.getMessage());
		}
		return new Result(Action.EXECUTE_SUCCESS, "执行成功");
	
	}
	
	
	private void redisToDB() {
		// 获取redis中所有的数据stringRedisTemplate.opsForList().rightPop(str)
		long length = stringRedisTemplate.opsForList().size("winddatas");
		System.out.println("the length is:" + length);
		for (int index = 0; index < length; index++) {
			jobService.date = new Date();
			String allValue = stringRedisTemplate.opsForList().rightPop("winddatas");
			jobService.insertRedisLog(allValue);
			if (allValue != null || !"".equals(allValue)) {
				JSONObject jsonAllValue = (JSONObject) JSONObject.parse(allValue);
				Set<String> keySet = jsonAllValue.keySet();
				if (keySet != null) {
					for (String strKey : keySet) {
						System.out.println(strKey);
					}

				}
				for (String strKey : keySet) {
					if (strKey.startsWith("raw")) {// 以raw开头，是原始数据

						JSONArray jsonArray = (JSONArray) jsonAllValue.get(strKey);
						List<HfData> aRawSeries = new ArrayList<HfData>();
						for (int i = 0; i < jsonArray.size(); i++) {
							JSONObject jsonObject = jsonArray.getJSONObject(i);
							Integer item_id = null;
							HfData hfData = new HfData();
							item_id = jsonObject.getIntValue("item_id");
							hfData.setItem_id(item_id);
							Date hdate = jsonObject.getDate("hdate");
							hfData.setHdate(hdate);
							Double valueDouble = Double.parseDouble(jsonObject.getString("value")+"");
							String result = String .format("%.2f",valueDouble);
							hfData.setValue(result);
							//hfData.setValue(jsonObject.getString("value")+" ");
							hfData.setTimestamp(jsonObject.getDate("timestamp"));
							hfData.setRemark(jsonObject.getString("remark"));
							 //jobService.insertSourceData(hfData);// 导入数据库
							aRawSeries.add(hfData);
						}
						
						jobService.batchInsertSourceData(aRawSeries);
						System.out.println(strKey + " done!");

					} else if (strKey.startsWith("augmented")) {

						List<HfData> aRawSeries = new ArrayList<HfData>();
						JSONArray jsonArray = (JSONArray) jsonAllValue.get(strKey);
						for (int i = 0; i < jsonArray.size(); i++) {
							JSONObject jsonObject = jsonArray.getJSONObject(i);
							HfData hfData = new HfData();
							hfData.setItem_id(jsonObject.getIntValue("item_id"));
							hfData.setHdate(jsonObject.getDate("hdate"));
							Double valueDouble = Double.parseDouble(jsonObject.getString("value")+"");
							String result = String .format("%.2f",valueDouble);
							hfData.setValue(result);
							hfData.setTimestamp(jsonObject.getDate("timestamp"));
							hfData.setRemark(jsonObject.getString("remark"));
							aRawSeries.add(hfData);
							
						}
					
						jobService.batchInsertDailyData(aRawSeries);
						System.out.println(strKey + " done!");
					}
				}
				

			}
		}
	}
	//从redis中获取三一重工的数据
	private List<BuildMain> findSanyiMainFillData() throws ParseException{
		String mainFillData = stringRedisTemplate.opsForValue().get("sanyidata");
		if(mainFillData==null || "".equals(mainFillData)){
			return null;
		}
		stringRedisTemplate.delete("sanyidata");
		JSONArray parse = (JSONArray) JSON.parse(mainFillData);
		List<BuildMain> buildList = new ArrayList<BuildMain>();
		Calendar calendar = Calendar.getInstance();
		for(int i = 0;i<parse.size();i++){
			BuildMain buildMain = new BuildMain();
			JSONObject jsonObject = (JSONObject) parse.get(i);
			buildMain.setBuild_area(jsonObject.get("build_area").toString());
			long millDate =Long.parseLong(jsonObject.get("build_date").toString());
			calendar.setTimeInMillis(millDate);
			buildMain.setBuild_date(calendar.getTime());
			buildMain.setBuild_value(Double.parseDouble(jsonObject.get("build_value").toString()));
			buildList.add(buildMain);
		}
		return buildList;
		
	}
	
	
	
	
/*
	try {
		BizLogger bizLogger = jobContext.getBizLogger();
		LOGGER.info("即将执行：" + jobContext);
		boolean flag = false;
		Map<String, String> jobExtParams = jobContext.getJob().getExtParams();
		if (jobExtParams != null) {
			String init = jobExtParams.get("init");
			if (init != null && init.equalsIgnoreCase("true")) {
				flag = true;
				LOGGER.info("执行全量数据导入");

			} else {
				LOGGER.info("执行增量数据导入");
			}
		}

		// 获取redis中所有的数据stringRedisTemplate.opsForList().rightPop(str)
		long length = stringRedisTemplate.opsForList().size("winddatas");
		System.out.println("队列长度是:" + length);
		for (int index = 0; index < length; index++) {
			jobService.date = new Date();
			String allValue = stringRedisTemplate.opsForList().rightPop("winddatas");
			jobService.insertRedisLog(allValue);
		
			if (allValue != null || !"".equals(allValue)) {
				JSONObject jsonAllValue = (JSONObject) JSONObject.parse(allValue);
				Set<String> keySet = jsonAllValue.keySet();
				if(keySet!=null){
					
					for (String strKey : keySet){
						System.out.println(strKey);
					}
					
				}
				for (String strKey : keySet) {
					if (strKey.startsWith("raw")) {// 以raw开头，是原始数据
						
						JSONArray jsonArray = (JSONArray) jsonAllValue.get(strKey);
						List<HfData> aRawSeries = new ArrayList<HfData>();
						for (int i = 0; i < jsonArray.size(); i++) {
							JSONObject jsonObject = jsonArray.getJSONObject(i);
							Integer item_id = null;
							hfData = new HfData();
							item_id = jsonObject.getIntValue("item_id");
							hfData.setItem_id(item_id);
							Date hdate = jsonObject.getDate("hdate");
							hfData.setHdate(hdate);
							hfData.setValue(jsonObject.getString("value"));
							hfData.setTimestamp(jsonObject.getDate("timestamp"));
							hfData.setRemark(jsonObject.getString("remark"));
							//jobService.insertSourceData(hfData);// 导入数据库
							aRawSeries.add(hfData);
						}
						jobService.batchInsertSourceData(aRawSeries);
						LOGGER.info(strKey+" done!");
						


					} else if (strKey.startsWith("augmented")) {
						
						List<HfData> aRawSeries = new ArrayList<HfData>();
						JSONArray jsonArray = (JSONArray) jsonAllValue.get(strKey);
						for (int i = 0; i < jsonArray.size(); i++) {
							JSONObject jsonObject = jsonArray.getJSONObject(i);
							hfData = new HfData();
							hfData.setItem_id(jsonObject.getIntValue("item_id"));
							hfData.setHdate(jsonObject.getDate("hdate"));
							hfData.setValue(jsonObject.getString("value"));
							hfData.setTimestamp(jsonObject.getDate("timestamp"));
							hfData.setRemark(jsonObject.getString("remark"));
							aRawSeries.add(hfData);
							if (flag == false) {
								jobService.InsertDailyData(hfData);// 导入数据库
								//rateCal.yoyIncremental(hfData);// 增量同比
								//rateCal.momIncremental(hfData);// 增量环比
								//rateCal.pobIncremental(hfData);// 增量定基比
							}
						}
						if(flag)
						{
							jobService.batchInsertDailyData(aRawSeries);
						}
						LOGGER.info(strKey+" done!");
					}
				}
//				if (flag == true) {// 全量
//					
//					rateCal.yoyAll();// 同比
//					LOGGER.info("全量同比"+" done!");
//					rateCal.momAll();// 环比
//					LOGGER.info("全量环比"+" done!");
//					rateCal.pobAll();// 定基比
//				}
				//简单起见，任何情况下都执行全量
				
				{
					jobService.truncateHighfreqData();
					rateCal.v7Function1InitDailyData();
					rateCal.v7Function2InitDailyData();
					rateCal.momAll();
					rateCal.yoyAll();
					rateCal.pobAll();
				}

			}
		}

//		try {
//			// 运行完会生成sql文件，然后上传
//			MyFTPClientUtils.upload(client);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}

		LOGGER.info("执行结束");
		jobContext.getJob().getExtParams();
		// 会发送到 LTS (JobTracker上)
		bizLogger.info("将数据导入到mysql中");

	} catch (Exception e) {
		LOGGER.info("Run job failed!", e);
		return new Result(Action.EXECUTE_FAILED, e.getMessage());
	}
	return new Result(Action.EXECUTE_SUCCESS, "执行成功");

	*/

//	private void augmentedAndCalculate(List<HfData> aRawSeries, Integer item_id, String fillCondition, boolean flag,
//			Date min, Date max) {
//
//		// 获取与原始值对应的日度数据的item_id
//		Integer daily_item_id = translateToDailyId(item_id);
//		Date latestInDb = null;
//		if (flag)// 全量
//		{
//			latestInDb = min;
//			// do nothing
//		} else {
//			latestInDb = selectLatestByItemId(daily_item_id);
//		}
//
//		if (fillCondition.equals("环比")) {
//			// 选择出所有数据
//			// 以2016年12月份数据为100
//			// 向前和向后计算
//			if (flag) {
//				// 全量抓取，数据结束时间必须是大于2016年12月31日，因为我们以12月数据作为基准,注意，逻辑上认为12月份肯定有数据
//				List<HfData> rawData = aRawSeries;
//				Map<Date, HfData> augmentedRawMap = new LinkedHashMap<Date, HfData>();
//				Map<Date, HfData> augmentedDailyMap = new LinkedHashMap<Date, HfData>();
//				for (int i = 0; i < rawData.size(); i++) {
//					Date now = rawData.get(i).getHdate();
//					Date next = rawData.get(i + 1).getHdate();
//
//					Date[] intervals = DateUtils.getDateInterval(now, next);
//					augmentedRawMap.put(rawData.get(i).getHdate(), rawData.get(i));
//					// now+1到next-1之间的数据用next的数据填充
//					for (Date date : intervals) {
//						HfData cloned = (HfData) BeanUtils.deepClone(rawData.get(i + 1));
//						cloned.setHdate(date);
//						augmentedRawMap.put(date, cloned);
//					}
//				}
//				// TODO:augmentedDaily中，12月份全月作为100,向前100/(1+value),向后100*(1+value)
//				Date[] dayOfDec2016 = DateUtils.getMonthDays("2016", "12");
//				for (Date d : dayOfDec2016) {
//					HfData data = new HfData();
//					data.setItem_id(daily_item_id);
//					data.setHdate(d);
//					data.setTimestamp(new Date());
//					data.setValue("100");
//					augmentedDailyMap.put(d, data);
//				}
//				Set<Date> days = augmentedRawMap.keySet();
//				int beforeMonths = 120;// 07年到16年，总共也就10年的数据，满打满算有120个月。
//				//向前向后计算，代价最小
//				for (int i = 1; i <= beforeMonths; i++) {
//					Date[] lastMonthDays = DateUtils.sliceOneMonthDate(days, "2016", "12", i);
//					if(lastMonthDays.length>0)
//					{
//						for(Date lmd:lastMonthDays)
//						{
//							Date nextMonthDay = DateUtils.nextOneMonth(lmd);
//							
//							HfData nextMonthAugmentedDailyData = augmentedDailyMap.get(nextMonthDay);
//							HfData nextMonthAugmentedRawData = augmentedRawMap.get(nextMonthDay);
//							
//							HfData cloned = nextMonthAugmentedDailyData.clone();
//							cloned.setHdate(lmd);
//							String calculated = String.valueOf(Double.valueOf(nextMonthAugmentedDailyData.getValue()).doubleValue()/(Double.valueOf(nextMonthAugmentedRawData.getValue()).doubleValue()+1));
//							cloned.setValue(calculated);
//							
//							augmentedDailyMap.put(lmd, cloned);
//						}
//					}else
//					{
//						break;
//					}
//				}
//				//16年12月份向后的月份
//				int aftermonth = DateUtils.getDateDiff(DateUtils.get20161231(), max)/30+1;
//				for (int i = 1; i <= aftermonth; i++) {
//					Date[] nextMonthDays = DateUtils.sliceOneMonthDate(days, "2016", "12", -i);
//					if(nextMonthDays.length>0)
//					{
//						for(Date lmd:nextMonthDays)
//						{
//							Date previosMonthDay = DateUtils.lastOneMonth(lmd);
//							
//							HfData previosMonthAugmentedDailyData = augmentedDailyMap.get(previosMonthDay);
//							HfData previosMonthAugmentedRawData   = augmentedRawMap.get(previosMonthDay);
//							
//							HfData cloned = previosMonthAugmentedDailyData.clone();
//							cloned.setHdate(lmd);
//							String calculated = String.valueOf(Double.valueOf(previosMonthAugmentedDailyData.getValue()).doubleValue()*(1+Double.valueOf(previosMonthAugmentedRawData.getValue()).doubleValue()));
//							cloned.setValue(calculated);
//							
//							augmentedDailyMap.put(lmd, cloned);
//						}
//					}else
//					{
//						break;
//					}
//					Collection<HfData> values = augmentedDailyMap.values();
//					List<HfData> vs = new ArrayList<HfData>(); 
//					vs.addAll(values);
//					Collections.sort((List<HfData>) vs, new Comparator<HfData>(){
//
//						@Override
//						public int compare(HfData o1, HfData o2) {
//							// TODO Auto-generated method stub
//							return o1.getHdate().compareTo(o2.getHdate());
//						}
//						
//					});
//				}
//
//			} else {
//
//			}
//
//		} else if (fillCondition.equals("平均")) {
//
//			if (flag) {
//
//			} else {
//
//			}
//		} else if (fillCondition.equals("公式")) {
//			if (flag) {
//
//			} else {
//
//			}
//		}
//
//	}
//
//
//
//	private Date selectLatestByItemId(Integer daily_item_id) {
//		// TODO Auto-generated method stub
//		return null;
//	}
//
//	private Integer translateToDailyId(Integer item_id) {
//		return jobService.translateToDailyId(item_id);
//	}
}
